package gp02.uniandes.dialgo.IO;

import java.util.ArrayList;

import gp02.uniandes.dialgo.mundo.Ciudad;
import gp02.uniandes.dialgo.mundo.Conexion;
import gp02.uniandes.dialgo.mundo.DiasSemana;
import gp02.uniandes.dialgo.mundo.ItinerarioRuta;
import gp02.uniandes.dialgo.mundo.RedDeTransporte;
import gp02.uniandes.dialgo.mundo.Salida;

public class Escritor
{
    // ---------------------------------------------------------------------------
    // CONSTANTES
    // ---------------------------------------------------------------------------
    private static final String LIMITE_20 = "--------------------";
    private static final String LIMITE_10 = "----------";
    private static final String NO_SOLUCION_INFINITO = "No solucion\ninfinito";
    private static final String ESPACIADOR = " ";
    // ---------------------------------------------------------------------------
    // CONSTRUCTOR
    // ---------------------------------------------------------------------------
    /**
     * Constructor de la clase por defecto sin parametros
     */
    public Escritor( )
    {

    }
    // ---------------------------------------------------------------------------
    // METODOS
    // ---------------------------------------------------------------------------
    /**
     * Metodo que escribe por salida estandar la solucion de los casos
     * @param caso El numero del caso que se resolvio
     * @param rutasReales TODO
     * @param ciudadOrigen TODO
     * @param ciudadDestino TODO
     * @param diaCaso TODO
     * @param horaDeseadaCaso TODO
     */
    public void escribirSolucion( boolean cambio, int caso, ArrayList<ItinerarioRuta> rutasReales, Ciudad ciudadOrigen, Ciudad ciudadDestino, DiasSemana diaCaso, int diaNumero, String horaDeseadaCaso, Lector lector )
    {
        // Caso en el que no haya solucion
        if( rutasReales.size( ) == 0 )
        {
            System.out.println( "Caso " + caso + Ciudad.SEPARADOR );
            System.out.println( "" + ciudadOrigen.getNombre( ) + ESPACIADOR + ciudadDestino.getNombre( ) + ESPACIADOR + diaCaso + ESPACIADOR + horaDeseadaCaso );
            System.out.println( LIMITE_10 );
            System.out.println( NO_SOLUCION_INFINITO );
            System.out.println( LIMITE_20 );
        }

        boolean cambioDia = false;
        // Recorre cada una de las rutas reales
        for( int i = 0; i < rutasReales.size( ); i++ )
        {
            ItinerarioRuta rutaActual = rutasReales.get( i );
            if( !cambio )
            {
                System.out.println( "Caso " + caso + Ciudad.SEPARADOR );
                System.out.println( "" + ciudadOrigen.getNombre( ) + ESPACIADOR + ciudadDestino.getNombre( ) + ESPACIADOR + diaCaso + ESPACIADOR + horaDeseadaCaso );
                System.out.println( LIMITE_10 );
            }
            String[] horaLlegada = { "0", "0" };

            // Se recorren todas las conexiones presentes en la ruta
            for( int j = 0; j < rutaActual.getConexiones( ).length; j++ )
            {
                Conexion conexionActual = rutaActual.getConexiones( )[ j ];
                Ciudad origen = conexionActual.getCiudadOrigen( );
                Ciudad destino = origen.getCiudadSiguiente( );

                // Es la primer conexion, es decir, el primer viaje
                if( j == 0 )
                {
                    int minutosRutaActual = rutaActual.getHoraSalidaEntero( ) * 60 + rutaActual.getMinutosSalidaEntero( ) + origen.getDemora( ) + destino.getTiempoEspera( );
                    horaLlegada = Ciudad.convertirHoras( minutosRutaActual, 0 );
                    String horasLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                    String minutosLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                    boolean posible = true;
                    if( Integer.parseInt( horasLlegada ) > 23 )
                    {
                        String[] data = Ciudad.convertirHorasDias( horasLlegada, minutosLlegada, diaNumero );
                        horasLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                        minutosLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                        int dia = Integer.parseInt( data[ 1 ] );
                        if( dia != -1 )
                        {
                            if( dia > diaNumero )
                                cambioDia = true;
                            diaCaso = RedDeTransporte.getDia( dia );
                            diaNumero = dia;
                        }
                        else
                        {
                            System.out.println( NO_SOLUCION_INFINITO );
                            System.out.println( LIMITE_20 );
                            posible = false;
                        }

                    }
                    if( posible && !cambioDia )
                        System.out.println( destino.getNombre( ) + ESPACIADOR + diaCaso + ESPACIADOR + horaDeseadaCaso + ESPACIADOR + horasLlegada + Ciudad.SEPARADOR + minutosLlegada );
                    else if( posible && cambioDia )
                    {
                        Salida inicial = ciudadOrigen.getCiudadSiguiente( ).getSalidaInicial( );
                        lector.resolverCambioDia( diaNumero, ( int )ciudadOrigen.getCodigo( ), ( int )ciudadDestino.getCodigo( ), ( int )inicial.getHora( ), ( int )inicial.getMinutos( ), caso );
                        cambioDia = true;
                        break;
                    }
                }
                // Las siguientes conexiones consideran tiempos adicionales
                else
                {
                    // Si la siguiente ciudad no es destino, considera el tiempo de espera en destino
                    if( !destino.esDestino( ) )
                    {
                        int minutosRutaActual = origen.getDemora( ) + destino.getTiempoEspera( ) + Integer.parseInt( horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 0 ] ) * 60 + Integer.parseInt( horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 1 ] );
                        horaLlegada = Ciudad.convertirHoras( minutosRutaActual, 0 );
                        String horasLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                        String minutosLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                        boolean posible = true;
                        if( Integer.parseInt( horasLlegada ) > 23 )
                        {
                            String[] data = Ciudad.convertirHorasDias( horasLlegada, minutosLlegada, diaNumero );
                            horasLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                            minutosLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                            int dia = Integer.parseInt( data[ 1 ] );
                            if( dia != -1 )
                            {
                                if( dia > diaNumero )
                                    cambioDia = true;
                                diaCaso = RedDeTransporte.getDia( dia );
                                diaNumero = dia;
                            }
                            else
                            {
                                System.out.println( NO_SOLUCION_INFINITO );
                                System.out.println( LIMITE_20 );
                                posible = false;
                            }

                        }
                        if( posible && !cambioDia )
                            System.out.println( destino.getNombre( ) + ESPACIADOR + diaCaso + ESPACIADOR + horaDeseadaCaso + ESPACIADOR + horasLlegada + Ciudad.SEPARADOR + minutosLlegada );
                        else if( posible && cambioDia )
                        {
                            Salida inicial = ciudadOrigen.getCiudadSiguiente( ).getSalidaInicial( );
                            lector.resolverCambioDia( diaNumero, ( int )ciudadOrigen.getCodigo( ), ( int )ciudadDestino.getCodigo( ), ( int )inicial.getHora( ), ( int )inicial.getMinutos( ), caso );
                            cambioDia = true;
                            break;
                        }
                    }
                    // Si la siguiente ciudad es destino, no considera el tiempo de espera en destino
                    else
                    {
                        int minutosRutaActual = origen.getDemora( ) + Integer.parseInt( horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 0 ] ) * 60 + Integer.parseInt( horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 1 ] );
                        horaLlegada = Ciudad.convertirHoras( minutosRutaActual, 0 );
                        String horasLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                        String minutosLlegada = horaLlegada[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                        boolean posible = true;
                        if( Integer.parseInt( horasLlegada ) > 23 )
                        {
                            String[] data = Ciudad.convertirHorasDias( horasLlegada, minutosLlegada, diaNumero );
                            horasLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 0 ];
                            minutosLlegada = data[ 0 ].split( Ciudad.SEPARADOR )[ 1 ];

                            int dia = Integer.parseInt( data[ 1 ] );
                            if( dia != -1 )
                            {
                                if( dia > diaNumero )
                                    cambioDia = true;
                                diaCaso = RedDeTransporte.getDia( dia );
                                diaNumero = dia;
                            }
                            else
                            {
                                System.out.println( NO_SOLUCION_INFINITO );
                                System.out.println( LIMITE_20 );
                                posible = false;
                            }

                        }
                        if( posible && !cambioDia )
                            System.out.println( destino.getNombre( ) + ESPACIADOR + diaCaso + ESPACIADOR + horaDeseadaCaso + ESPACIADOR + horasLlegada + Ciudad.SEPARADOR + minutosLlegada );
                        else if( posible && cambioDia )
                        {
                            Salida inicial = ciudadOrigen.getCiudadSiguiente( ).getSalidaInicial( );
                            lector.resolverCambioDia( diaNumero, ( int )ciudadOrigen.getCodigo( ), ( int )ciudadDestino.getCodigo( ), ( int )inicial.getHora( ), ( int )inicial.getMinutos( ), caso );
                            cambioDia = true;
                            break;
                        }
                    }
                }
            }
            if( !cambioDia )
            {
                System.out.println( rutaActual.getTiempoTotal( ) );
                System.out.println( LIMITE_20 );
            }
        }
    }
}
